const { src, dest, series, parallel, watch } = require('gulp')
const plugins = require('gulp-load-plugins')() // 2. 自动加载插件

const del = require('del')
const bs = require('browser-sync').create()

const templateConfig = require('./templateConfig.js')

const PATH_CONFIG = {
  style: 'src/assets/styles/*.scss',
  script: 'src/assets/scripts/*.js',
  page: 'src/*.html',
  image: 'src/assets/images/**',
  font: 'src/assets/fonts/**',
  extra: 'public/**'
}

// 1.文件清除
const clean = () => {
  return del(['dist', 'tmp'])
}

// 3.样式编译
const style = () => {
  return (
    src(PATH_CONFIG.style, { base: 'src' }) // 指定输出路径层级
      // .pipe(plugins.sass()) // 最后一个 } 没有换行
      .pipe(plugins.sass({ outputStyle: 'expanded' }))
      .pipe(dest('tmp'))
      .pipe(bs.reload({ stream: true }))
  )
}
// 4.js 编译
const script = () => {
  return (
    src(PATH_CONFIG.script, { base: 'src' })
        .pipe(
            plugins.babel({
              presets: ["@babel/preset-env"]
            })
        )
        .pipe(dest('tmp'))
        .pipe(bs.reload({ stream: true }))
  )
}
// 5.html 模板编译
const page = () => {
  return (
    src(PATH_CONFIG.page)
        .pipe(
            plugins.swig({
              data: templateConfig, // 注入模板数据
              defaults: { cache: false } // 禁用缓存防止热更新失效
            })
        )
        .pipe(dest('tmp'))
        .pipe(bs.reload({ stream: true }))
  )
}

// 6.图片和字体文件
// 仅对于 build
const image = () => {
  return (
    src(PATH_CONFIG.image, { base: 'src' })
        .pipe(
            plugins.imagemin()
        )
        .pipe(dest('dist'))
  )
}
// 仅对于 build
const font = () => {
  return (
    src(PATH_CONFIG.font, { base: 'src' })
        .pipe(
            plugins.imagemin()
        )
        .pipe(dest('dist'))
  )
}

// 7.其他文件 (public)
const extra = () => {
  return src(PATH_CONFIG.extra, { base: 'public' }).pipe(dest('dist'))
}

// 8.开发服务器
const server = () => {
  watch(PATH_CONFIG.style, style)
  watch(PATH_CONFIG.script, script)
  watch(PATH_CONFIG.page, page)

  watch([
    PATH_CONFIG.image,
    PATH_CONFIG.font,
    PATH_CONFIG.extra,
  ], bs.reload)

  bs.init({
    notify: false,
    server: {
      baseDir: ['tmp', 'src', 'public'],
      // files: 'tmp/**', // 测试不生效 ??
      routes: {
        '/node_modules': 'node_modules' // html 引用了 本地node_module库
      }
    }
  })
}

// 9.useref 插件处理js,css文件合并及压缩
const useref = () => {
  return (
    src('tmp/*.html', { base: 'tmp' })
        .pipe(
            plugins.useref({ searchPath: ['tmp', '.'] })
        )
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss())) // 驼峰命名法
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({ // htmlmin 需要配置对应的压缩项
          collapseWhitespace: true,
          minifyCSS: true,
          minifyJS: true
        })))
        .pipe(dest('dist'))
  )
}

const compiler = parallel(style, script, page)
const build = series(
  clean,
  parallel(
    series(compiler, useref),
    extra,
    image,
    font
  )
)
const develop = series(clean, compiler, server)

module.exports = {
  clean,
  build,
  develop
}
